<body style="padding:0; border:0; margin: 15px; background-color: white;" tabindex="1">
  <style>
    .xlsx-content {
      margin: -15px;
      margin-bottom: 30px;
    }
    .xlsx-tabs {
      position: fixed;
      bottom: 0;
      left: 0;
      right: 0;
      display: flex;
      flex-direction: row;
      height: 30px;
      background: #98a7b9;
      overflow-x: auto;
      overflow-y: hidden;
      white-space: nowrap;
      border-top: 1px solid #777;
    }
    .xlsx-tabs .tab {
      padding: 0 10px;
      margin-right: 3px;
      border-left: 1px solid #ddd;
      background: #e2e2e2;
      height: 26px;
      line-height: 26px;
      box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.2);
      color: #333;
      cursor: default;
      user-select: none;
    }
    .xlsx-tabs .tab.active {
      background: white;
    }
    .xlsx-content table {
      border-collapse: collapse;
    }
    .xlsx-content td {
      border: 1px solid #eee;
      padding: 3px;
    }
  </style>

  <div id="the-doc"><canvas id="the-canvas"></canvas></div>

  <script>
    const div = document.getElementById('the-doc');

    function finishWithWindowCapture(previewPath, startedAt = Date.now()) {
      // Remove scroll bars or they appear in the capture on Windows
      document.body.style.overflow = 'hidden';

      // Wait up to 1 sec for images in the rendered HTML to finish loading
      const waitingForImage = Array.from(document.querySelectorAll('img')).find(
        i => i.complete === false
      );
      if (waitingForImage && Date.now() - startedAt < 1000) {
        setTimeout(() => finishWithWindowCapture(previewPath, startedAt), 50);
        return;
      }

      window.requestAnimationFrame(() => {
        window.requestAnimationFrame(() => {
          window.requestAnimationFrame(async () => {
            await window.electronAPI.finishCapture(previewPath);
            document.title = 'Finished';
          });
        });
      });
    }

    async function runPDFCapture({ previewPath }) {
      const canvas = document.getElementById('the-canvas');
      const context = canvas.getContext('2d');
      const el = document.createElement('script');
      el.onload = async () => {
        pdfjsLib.GlobalWorkerOptions.workerSrc = './pdfjs-4.3.136/build/pdf.worker.js';

        const buffer = await window.electronAPI.previewFileAsBuffer();
        const pdf = await pdfjsLib.getDocument(buffer, {
          cMapUrl: './pdfjs-4.3.136/web/cmaps',
          cMapPacked: true,
        });

        const page = await pdf.getPage(1);

        const viewport = page.getViewport({ scale: 1 });
        const scale = window.outerWidth / (viewport.width || viewport.viewBox[2]);
        const scaledViewport = page.getViewport({ scale: scale });

        scaledViewport.height = scaledViewport.height || viewport.viewBox[3] * scale;
        scaledViewport.width = scaledViewport.width || viewport.viewBox[2] * scale;
        if (Number.isNaN(scaledViewport.transform[0])) {
          scaledViewport.transform = [scale, 0, 0, -scale, 0, scaledViewport.height];
        }
        canvas.height = scaledViewport.height;
        canvas.width = scaledViewport.width;
        canvas.style.height = scaledViewport.height / window.devicePixelRatio + 'px';
        canvas.style.width = scaledViewport.width / window.devicePixelRatio + 'px';

        const renderTask = page.render({
          canvasContext: context,
          viewport: scaledViewport,
        });

        await renderTask.promise.then(function() {
          canvas.toBlob(blob => {
            const reader = new FileReader();
            reader.addEventListener('loadend', async () => {
              await window.electronAPI.finishWithData(previewPath, new Uint8Array(reader.result));
              document.title = 'Finished';
            });
            reader.readAsArrayBuffer(blob);
          });
        });
      };
      el.src = `pdfjs-4.3.136/build/pdf.js`;
      document.body.appendChild(el);
    }

    async function runXLSX({ previewPath }) {
      const data = await window.electronAPI.previewFileAsBuffer();
      const xlsx = document.createElement('script');
      xlsx.onload = () => {
        const workbook = window.XLSX.read(data, {
          type: 'array',
          cellStyles: true,
          cellHTML: true,
        });

        div.innerHTML = '';

        if (mode === 'capture') {
          div.innerHTML = window.XLSX.write(workbook, {
            sheet: workbook.SheetNames[0],
            type: 'string',
            bookType: 'html',
            header: '<div>',
            footer: '</div>',
          });
          finishWithWindowCapture(previewPath);
        } else {
          const content = document.createElement('div');
          content.classList.add('xlsx-content');
          div.appendChild(content);
          const tabs = document.createElement('div');
          tabs.classList.add('xlsx-tabs');
          div.appendChild(tabs);

          const showTab = sheetName => {
            document.querySelectorAll('.tab').forEach(tab => tab.classList.remove('active'));
            const tab = document.querySelector(`[data-sheet-name="${sheetName}"]`);
            if (tab) tab.classList.add('active');

            content.innerHTML = window.XLSX.write(workbook, {
              sheet: sheetName,
              type: 'string',
              bookType: 'html',
              header: '<div>',
              footer: '</div>',
            });
          };

          workbook.SheetNames.forEach(sheetName => {
            const tab = document.createElement('div');
            tab.classList.add('tab');
            tab.innerText = sheetName;
            tab.dataset.sheetName = sheetName;
            tab.addEventListener('click', () => showTab(sheetName));
            tabs.appendChild(tab);
          });

          showTab(workbook.SheetNames[0]);
        }
      };
      xlsx.src = './xlsx-0.18.5/xlsx.full.min.js';
      document.body.appendChild(xlsx);
    }

    async function runPrism({ filePath, previewPath, mode }) {
      const ext = filePath.split('.').pop();
      const str = await window.electronAPI.previewFileAsString({
        truncate: mode === 'capture',
      });

      const grammars = {
        html: 'html',
        xml: 'xml',
        svg: 'svg',
        css: 'css',
        js: 'javascript',
        c: 'c',
        h: 'c',
        cs: 'csharp',
        cc: 'cpp',
        cpp: 'cpp',
        patch: 'diff',
        go: 'go',
        java: 'java',
        json: 'json',
        jsonp: 'json',
        tex: 'latex',
        m: 'objectivec',
        mm: 'objectivec',
        py: 'python',
        jsx: 'jsx',
        tsx: 'tsx',
        rb: 'ruby',
        rs: 'rust',
        sql: 'sql',
        swift: 'swift',
        ts: 'typescript',
        yaml: 'yaml',
        txt: 'clike',
        log: 'clike',
      };

      const grammar = grammars[ext] || 'clike';

      // Attach Prism CSS
      const link = document.createElement('link');
      link.rel = 'stylesheet';
      link.href = './prism-1.15.0/prism.css';
      document.body.appendChild(link);
      document.body.style.margin = '0';

      // Attach <pre><code class="language-XXX">{text}</code></pre> to the DOM
      div.innerHTML = '';
      if (mode !== 'capture') {
        div.style.opacity = 0;
      }
      const preEl = document.createElement('pre');
      preEl.style = 'min-height: 100%; margin: 0; border-radius: 0;';
      div.appendChild(preEl);

      const codeEl = document.createElement('code');
      codeEl.textContent = str;
      codeEl.classList.add(`language-${grammar}`);
      preEl.appendChild(codeEl);

      // Load the Prism script and capture/show the DOM when it's completed
      const finish = () => {
        const stylesReady = window.getComputedStyle(preEl).fontFamily.includes('Monaco');
        if (!stylesReady) {
          setTimeout(finish, 1);
          return;
        }

        div.style.opacity = 1;
        if (mode === 'capture') {
          finishWithWindowCapture(previewPath);
        }
      };

      const script = document.createElement('script');
      script.onload = finish;
      script.src = './prism-1.15.0/prism.js';
      document.body.appendChild(script);
    }

    async function runMammoth({ previewPath, mode }) {
      div.innerHTML = await window.electronAPI.previewFileAsMammothHTML();
      if (mode === 'capture') {
        finishWithWindowCapture(previewPath);
      }
    }

    async function runSnarkdown({ previewPath, mode }) {
      div.innerHTML = await window.electronAPI.previewFileAsSnarkdownHTML();
      div.style.fontFamily =
        '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"';
      if (mode === 'capture') {
        finishWithWindowCapture(previewPath);
      }
    }

    const { mode, filePath, previewPath, strategy } = JSON.parse(
      decodeURIComponent(window.location.search.substr(1))
    );

    window.requestAnimationFrame(() => {
      if (strategy === 'pdfjs') {
        if (mode === 'capture') {
          runPDFCapture({ previewPath });
        } else {
          // To view PDFs we use the separate pdfviewer included with pdfjs
        }
      } else if (strategy === 'mammoth') {
        runMammoth({ mode, previewPath });
      } else if (strategy === 'snarkdown') {
        runSnarkdown({ mode, previewPath });
      } else if (strategy === 'prism') {
        runPrism({ filePath, mode, previewPath });
      } else if (strategy === 'xlsx') {
        runXLSX({ mode, previewPath });
      }
    });
  </script>
</body>
